From 61ecce504bab5f0ec96fde06a8554e5cceabb19e Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Tue, 23 Mar 2010 07:28:33 +0000 Subject: [PATCH] x86_32: Relocate multiboot modules to below 1GB. Otherwise Xen cannot access them later during boot. GRUB2 places modules as high as possible below 4GB, which has been causing boot failure. Signed-off-by: Keir Fraser --- xen/arch/x86/boot/Makefile | 2 +- xen/arch/x86/boot/build32.mk | 2 +- xen/arch/x86/boot/reloc.c | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/boot/Makefile b/xen/arch/x86/boot/Makefile index 90856f918e..630b19d027 100644 --- a/xen/arch/x86/boot/Makefile +++ b/xen/arch/x86/boot/Makefile @@ -4,6 +4,6 @@ head.o: reloc.S BOOT_TRAMPOLINE := $(shell sed -n 's,^\#define[[:space:]]\+BOOT_TRAMPOLINE[[:space:]]\+,,p' $(BASEDIR)/include/asm-x86/config.h) %.S: %.c - RELOC=$(BOOT_TRAMPOLINE) $(MAKE) -f build32.mk $@ + RELOC=$(BOOT_TRAMPOLINE) XEN_BITSPERLONG=$(patsubst x86_%,%,$(TARGET_SUBARCH)) $(MAKE) -f build32.mk $@ reloc.S: $(BASEDIR)/include/asm-x86/config.h diff --git a/xen/arch/x86/boot/build32.mk b/xen/arch/x86/boot/build32.mk index 01f7480b52..0de9c15af2 100644 --- a/xen/arch/x86/boot/build32.mk +++ b/xen/arch/x86/boot/build32.mk @@ -22,6 +22,6 @@ CFLAGS += -Werror -fno-builtin -msoft-float $(LD) $(LDFLAGS_DIRECT) -N -Ttext $(RELOC) -o $@ $< %.o: %.c - $(CC) $(CFLAGS) -c $< -o $@ + $(CC) $(CFLAGS) -DXEN_BITSPERLONG=$(XEN_BITSPERLONG) -c $< -o $@ reloc.o: $(BASEDIR)/include/asm-x86/config.h diff --git a/xen/arch/x86/boot/reloc.c b/xen/arch/x86/boot/reloc.c index e3333d36b8..233a94f347 100644 --- a/xen/arch/x86/boot/reloc.c +++ b/xen/arch/x86/boot/reloc.c @@ -70,8 +70,28 @@ multiboot_info_t *reloc(multiboot_info_t *mbi_old) (module_t *)mbi->mods_addr, mbi->mods_count * sizeof(module_t)); mbi->mods_addr = (u32)mods; for ( i = 0; i < mbi->mods_count; i++ ) + { +#if XEN_BITSPERLONG == 32 + /* + * 32-bit Xen only maps bottom 1GB of memory at boot time. + * Relocate modules which extend beyond this (GRUB2 in particular + * likes to place modules as high as possible below 4GB). + */ +#define BOOTMAP_END (1ul<<30) /* 1GB */ + static void *mod_alloc = (void *)BOOTMAP_END; + u32 mod_len = mods[i].mod_end - mods[i].mod_start; + if ( mods[i].mod_end > BOOTMAP_END ) + { + mod_alloc = (void *) + (((unsigned long)mod_alloc - mod_len) & ~15ul); + mods[i].mod_start = (u32)memcpy( + mod_alloc, (char *)mods[i].mod_start, mod_len); + mods[i].mod_end = mods[i].mod_start + mod_len; + } +#endif if ( mods[i].string ) mods[i].string = (u32)reloc_mbi_string((char *)mods[i].string); + } } if ( mbi->flags & MBI_MEMMAP ) -- 2.30.2